#include<dlfcn.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<time.h>
#include<unistd.h>
#include "els.h"
typedef char* LNI;
LNI els_core_exec(int argc,LNI* argv);
void els_core_val(void);
void els_core_str(void);
void els_core_type(void);
void els_core_exit(void);
void els_core_post(void);
void els_core_inc(void);
void els_core_eval(void);
void els_core_end(void);
void els_core_print(void);
void els_core_input(void);
void els_core_shell(void);

static int rt_lock=0;
static char rt_str[1024];
static char tmp[1204];

static char** core_argv;
static int    core_argc;
static void core_getargv (void){
    els_Typesystem_Object lo = els_getstack(1);
    if (!els_isnum(lo)) els_pushnull();
    else{
        int n = (int)els_getnum(lo);
        if (n > core_argc) els_pushnull();
        else els_pushstr(core_argv[n]);
    }
}
static void core_getargc (void){
    els_pushnum(core_argc);
}

LNI els_core_exec(int argc,LNI* argv){
    core_argc = argc;
    core_argv = argv;
    
    
    els_register("参数", core_getargv);
    els_register("参数个数", core_getargc);
    
    els_register("argv", core_getargv);
    els_register("argc", core_getargc);
    

    els_load_lib();
    els_dofile (argv[0]);
    return rt_str;
}



void els_FFI_C(void){
    char incdir[512]="/usr/els/lib/";
    typedef  char* (*ELS_C_FFI)(char* a1,char* a2,char* a3,char* a4,char* a5,char* a6,char* a7,char* a8);
    if(els_isstr(els_getstack(1))&&els_isstr(els_getstack(2))){
        strcat(incdir,els_getvalue(els_getstack(1)));
        char *libname = els_getstr(els_getstack(1));
        char *funcname = els_getstr(els_getstack(2));
        void* _ptr_dll = dlopen(libname,RTLD_NOW);
        if (!_ptr_dll) _ptr_dll = dlopen(incdir,RTLD_NOW);
        if(!_ptr_dll)   els_error("无法加载C库");
        ELS_C_FFI c_api;
        c_api = (ELS_C_FFI)dlsym(_ptr_dll,funcname);
        char* tmp = c_api(els_getvalue(els_getstack(3)),els_getvalue(els_getstack(4)),els_getvalue(els_getstack(5)),els_getvalue(els_getstack(6)),els_getvalue(els_getstack(7)),els_getvalue(els_getstack(8)),els_getvalue(els_getstack(9)),els_getvalue(els_getstack(10)));
        els_pushstr((char*)(tmp));
    }
    return;
}
void els_load_lib(){
    els_register("库", els_FFI_C);
    els_register("值",els_core_val);
    els_register("字",els_core_str);
    els_register("类",els_core_type);
    els_register("退",els_core_exit);
    els_register("传",els_core_post);
    els_register("尾",els_core_end);
    els_register("引",els_core_inc);
    els_register("释",els_core_eval);
    els_register("打印",els_core_print);
    els_register("输入",els_core_input);
    els_register("调",els_core_shell);


    els_register("call", els_FFI_C);
    els_register("val",els_core_val);
    els_register("str",els_core_str);
    els_register("type",els_core_type);
    els_register("exit",els_core_exit);
    els_register("post",els_core_post);
    els_register("end",els_core_end);
    els_register("import",els_core_inc);
    els_register("eval",els_core_eval);
    els_register("print",els_core_print);
    els_register("input",els_core_input);
    els_register("shell",els_core_shell);
}


void els_core_val(void){
    els_pushnum(atoi(els_getvalue(els_getstack(1))));
}
void els_core_str(void){
    els_pushstr(els_getvalue(els_getstack(1)));
}
void els_core_type(void){
    els_Typesystem_Object o = els_getstack(1);
    int t;
    if (o == ELS_NO_OBJECT) els_error("方法 '类' 缺少参数");
    t = els_type(o);
    switch (t){
        case ELS_TYPE_NULL      : els_pushstr("空");      break;
        case ELS_TYPE_NUMBER    : els_pushstr("数");       break;
        case ELS_TYPE_STRING    : els_pushstr("字");       break;
        case ELS_TYPE_ARRAY     : els_pushstr("组");      break;
        case ELS_TYPE_FC        : els_pushstr("法");      break;
        default                 : els_pushstr("另");      break;
    }
}
void els_core_exit(void){
    els_pushnum(1);
    if(els_getstack(1)==ELS_NO_OBJECT) exit(0);
    else if(els_isnum(els_getstack(1))){
        exit((int)(els_getnum(els_getstack(1))));
    }
    exit(0);
}
void els_core_end(void){
}
void els_core_post(void){
    if(rt_lock==1) return;
    else{ 
        sprintf(rt_str,"%s",els_getvalue(els_getstack(1)));
    }   
    rt_lock=1;
    return;
}
void els_core_inc(void){
    char incdir[512]="/usr/els/inc/";
    if(els_getstack(1)==ELS_NO_OBJECT) els_error("方法 引 缺少参数");
    FILE *fi = fopen(els_getvalue(els_getstack(1)),"r");
    if(fi>0){
        fclose(fi);
        els_dofile(els_getvalue(els_getstack(1)));
    }else{
        strcat(incdir,els_getvalue(els_getstack(1)));
        strcat(incdir,".els");
        els_dofile(incdir);
    }
}
void els_core_print(void){
    if(els_type(els_getstack(1))==ELS_TYPE_NULL) return;
    printf("%s\n",els_getvalue(els_getstack(1)));
}
void els_core_input(void){
    char s;
    scanf("%s%c",tmp,&s);
    els_pushstr(tmp);
}
void els_core_shell(void){
    els_pushnum(system(els_getvalue(els_getstack(1))));
}
void els_core_eval(void){
    if(els_type(els_getstack(1))==ELS_TYPE_NULL) return;
    els_dostring(els_getstr(els_getstack(1)));
}